package utils

import (
	"reflect"
	"regexp"
	"strings"
)

const (
	defaultStructTagName = "orm"
)

//判断字符是还否是纯数字
func CheckIsNumber(s string) bool {
	match, _ := regexp.MatchString("^[0-9]*$", s)
	return match
}
//剔除不需要更新的字段
func NeedUpdateFields(m interface{}, exclude ...string) []string {
	var fields []string
	refTypeOf := reflect.TypeOf(m)
	refT := refTypeOf.Elem()
	for i := 0; i < refT.NumField(); i++ {
		if b, _ := parseStructTag(refT.Field(i).Tag.Get(defaultStructTagName)); b["-"] {
			continue
		}
		if !IsExistItem(refT.Field(i).Name, exclude) {
			fields = append(fields, refT.Field(i).Name)
		}
	}
	return fields
}

//判断值是否在slice
func IsExistItem(value interface{}, array interface{}) bool {
	switch reflect.TypeOf(array).Kind() {
	case reflect.Slice:
		s := reflect.ValueOf(array)
		for i:=0;i<s.Len();i++ {
			if reflect.DeepEqual(value, s.Index(i).Interface()) {
				return  true
			}
		}
	}
	return false
}


//剔除内容为空的字段
func ReflectModelFields(m interface{}, field... string) ([]string, error) {
	//field := make([]string, 0)
	refTypeOf := reflect.TypeOf(m)
	refValueOf := reflect.ValueOf(m)
	refT := refTypeOf.Elem()
	refV := refValueOf.Elem()
	for i := 0; i < refT.NumField(); i++ {
		val := refV.Field(i).Interface()
		fname := refT.Field(i).Name

		if b, _ := parseStructTag(refT.Field(i).Tag.Get(defaultStructTagName)); b["-"] {
			continue
		}

		switch val.(type){
			case string:
				if len(val.(string))<= 0 {
					continue
				}
			case int:
				if val.(int) == 0 {
					continue
				}
			case int32:
				if val.(int32) == 0 {
					continue
				}
			case int64:
				if val.(int64) == 0 {
					continue
				}
			default:

		}

		if fname != "CreatedAt" {
			field = append(field, fname)
		}
	}
	return field, nil
}


var supportTag = map[string]int{
	"-":            1,
	"null":         1,
	"index":        1,
	"unique":       1,
	"pk":           1,
	"auto":         1,
	"auto_now":     1,
	"auto_now_add": 1,
	"size":         2,
	"column":       2,
	"default":      2,
	"rel":          2,
	"reverse":      2,
	"rel_table":    2,
	"rel_through":  2,
	"digits":       2,
	"decimals":     2,
	"on_delete":    2,
	"type":         2,
}
var defaultStructTagDelim = ";"

// parse struct tag string
func parseStructTag(data string) (attrs map[string]bool, tags map[string]string) {
	attrs = make(map[string]bool)
	tags = make(map[string]string)
	for _, v := range strings.Split(data, defaultStructTagDelim) {
		if v == "" {
			continue
		}
		v = strings.TrimSpace(v)
		if t := strings.ToLower(v); supportTag[t] == 1 {
			attrs[t] = true
		} else if i := strings.Index(v, "("); i > 0 && strings.Index(v, ")") == len(v)-1 {
			name := t[:i]
			if supportTag[name] == 2 {
				v = v[i+1 : len(v)-1]
				tags[name] = v
			}
		} else {
			panic("unsupport orm tag")
		}
	}
	return
}
